﻿//-----------------------------------------------------------------------
// <copyright file="ClassMemberDef.cs" company="tuliprules.org">
//     Copyright (c) 2010 tuplelister, tuliprules.org.
// </copyright>
// <summary>This is the ClassMemberDef class.</summary>
//-----------------------------------------------------------------------

namespace Tulip.Rules.CodeGen.Templates
{
    using System.Collections.Generic;
    using System.Linq;
    using Engine.Models.ClosedWorld;
    using Models.ClosedWorld;

    /// <summary>
    /// Represents a record for a tuple class member definition.
    /// Tuple classes represent the abstract notion of a relational
    /// tuple and are bound internally to some concrete data/behaviour
    /// representing a runtime fact.  Class members are always generated 
    /// as properties.  If they are bound to behaviour only (e.g., a
    /// method that returns void), the tuple class member returns a
    /// Void instance.
    /// </summary>
    public struct ClassMemberDef
    {
        /// <summary>
        /// Gets or sets the Member Definition.
        /// </summary>
        public MemberDef MemberDef { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the member value is to be cached.
        /// </summary>
        public bool IsCached { get; set; }

        /// <summary>
        /// Gets or sets the type returned by member.  'void' is represented as System.Object.
        /// </summary>
        public System.Type ReturnType { get; set; }

        /// <summary>
        /// Gets a list of tuple class member definitions.  The list is populated from data
        /// passed as a Class Definition.
        /// </summary>
        /// <param name="classDef">The class definition.</param>
        /// <returns>
        /// A list of class member defintions.
        /// </returns>
        public static List<ClassMemberDef> GetClassMemberDefList(ClassDef classDef)
        {
            var memberDefList = new List<ClassMemberDef>();

            if (classDef == null)
            {
                return memberDefList;
            }

            foreach (var mbrDef in classDef.Members)
            {
                var isCached = mbrDef.IsCached;

                // If Const or ReadOnly field, then automatically cache.  If a Property Set, then don't cache
                if (mbrDef.BoundMemberKind == MemberKind.Const || mbrDef.BoundMemberKind == MemberKind.FieldReadOnly)
                {
                    isCached = true;
                }
                else if (mbrDef.BoundMemberKind == MemberKind.PropertySet)
                {
                    isCached = false;
                }

                mbrDef.IsCached = isCached;

                // If no return parameter is provided, the property will be typed as an object...
                var retParamDef = mbrDef.Parameters.FirstOrDefault(pd => pd.Return);
                var returnType = System.Type.GetType("Tulip.Rules.Void");

                if (retParamDef != null)
                {
                    returnType = System.Type.GetType(retParamDef.TypeName);
                }

                memberDefList.Add(new ClassMemberDef { ReturnType = returnType, IsCached = isCached, MemberDef = mbrDef });
            }

            return memberDefList;
        }
    }
}
